package ws

import (
	"fmt"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/valyala/fasthttp"
	"github.com/valyala/fasthttp/fasthttpadaptor"
	"github.com/zishang520/engine.io/v2/types"
	"github.com/zishang520/socket.io/v2/socket"
)

var Clients = make(map[string]*socket.Socket)

func AddClient(key string, client *socket.Socket) {
	if _, ok := Clients[key]; !ok {
		Clients[key] = client
	}
}

func RemoveClient(key string) {
	delete(Clients, key)
}

func GetSocketLength() int {
	return len(Clients)
}

func InitWsServer(port string) {
	c := socket.DefaultServerOptions()
	c.SetServeClient(true)
	c.SetMaxHttpBufferSize(1000000)
	c.SetConnectTimeout(1000 * time.Millisecond)
	c.SetCors(&types.Cors{
		Origin:      "*",
		Credentials: true,
	})
	socketio := socket.NewServer(nil, nil)
	socketio.On("connection", func(clients ...interface{}) {
		client := clients[0].(*socket.Socket)

		if authMap, ok := client.Handshake().Auth.(map[string]interface{}); ok {
			auth := authMap["auth"].(string)
			fmt.Println("connection", auth)
			AddClient(auth, client)
		}

		client.On("message", func(args ...interface{}) {
			client.Emit("message-back", args...)
		})

		client.On("message-with-ack", func(args ...interface{}) {
			ack := args[len(args)-1].(socket.Ack)
			ack(args[:len(args)-1], nil)
		})

		client.On("disconnect", func(...any) {
			auth := client.Handshake().Auth.(map[string]interface{})["auth"].(string)
			fmt.Println("disconnection", auth)
			RemoveClient(auth)
		})

	})

	go fasthttp.ListenAndServe(":"+port, fasthttpadaptor.NewFastHTTPHandler(socketio.ServeHandler(c)))

	exit := make(chan struct{})
	SignalC := make(chan os.Signal, 1)

	signal.Notify(SignalC, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
	go func() {
		for s := range SignalC {
			switch s {
			case syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT:
				close(exit)
				return
			}
		}
	}()

	<-exit
	socketio.Close(nil)
}
